/*
 * @Author: xujiawei 
 * @Date: 2021-10-27 18:51:30 
 * @Last Modified by: xujiawei
 * @Last Modified time: 2021-10-27 19:05:55
 * 
 * 分帧处理封装
 */

// 使用实例
// class ExampleFrameTask extends cc.Component {
//     start() {
//         let data = []; // 一堆要处理的数据
//         let frameData = []; // 每帧要处理的数据
//         const frameDeal = 5; // 每帧要处理的数量
//         const total = frameData.length;
//         let deal = 0;
//         const taskName = 'xxFrameTask';
//         FrameTaskManager.getInstance().removeTask(taskName);
//         let createFrameTask = (waitingData: any[]) => {
//             let call = function (data: any[]) {
//                 for (let d of data) {
//                     // todo: do some thing
//                     deal++;
//                 }
//                 if (deal == total) {
//                     // 分帧处理完毕
//                 }
//             }.bind(this, waitingData);
//             FrameTaskManager.getInstance().addTask(new FrameTask(call, taskName));
//         }

//         for (let item of data) {
//             frameData.push(item);
//             if (frameData.length == frameDeal) {
//                 createFrameTask(frameData);
//                 frameData = [];
//             }
//         }
//         if (frameData.length) {
//             createFrameTask(frameData);
//             frameData = [];
//         }
//     }

//     update(dt) {
//         // 最好在全局的定时器调用work
//         FrameTaskManager.getInstance().working(dt);
//     }
// }


import { Log } from "./Log";

export class FrameTask {
    public name: string = "";
    public taskFun: Function = null;
    public forceInOneFrame: boolean = false; // 独占一帧

    public constructor(cb: Function, name: string) {
        this.name = name;
        this.taskFun = cb;
    }
}

// 分帧加载管理器，用于处理耗时操作
export class FrameTaskManager {
    private static _instance: FrameTaskManager = null;
    private taskQueue: Array<FrameTask> = null;

    public static getInstance(): FrameTaskManager {
        if (this._instance == null) {
            this._instance = new FrameTaskManager();
        }
        return FrameTaskManager._instance;
    }

    public purge() {
        FrameTaskManager._instance = null;
    }

    private constructor() {
        this.taskQueue = new Array<FrameTask>();
    }

    public addTask(task: FrameTask) {
        this.taskQueue.push(task);
    }

    public removeTask(taskName: string) {
        let removeArr: Array<number> = [];

        for (let index = 0; index < this.taskQueue.length; index++) {
            const element: FrameTask = this.taskQueue[index];
            if (element.name === taskName) {
                removeArr.push(index);
            }
        }
        for (let index = removeArr.length - 1; index >= 0; index--) {
            const element: number = removeArr[index];
            this.taskQueue.splice(element, 1);
        }
    }

    public working(dt: number) {
        let startTime = Date.now();
        do {
            if (this.taskQueue.length <= 0) {
                break;
            }

            let task = this.taskQueue.shift();
            try {
                task.taskFun && task.taskFun();
            } catch (e) {
                Log.error("FrameTask Error", task.name, e.message);
            }

            let workTime = Date.now() - startTime;
            // Log.info("[FrameTaskManager] [working]", workTime, task.name);
            if (workTime >= 15 || task.forceInOneFrame) {
                if (workTime > 33) {
                    // Log.warn("[FrameTaskManager] [working]", workTime, task.name);
                }
                break;
            }
        } while (true)
    }
};
